import { reactive, ref, onMounted } from 'vue';

interface usePaginationConfig {
  /** 表数据获取函数 */
  load: loadPaginationRequest;
  /** 表数据获取检验函数 */
  verifyParameter?(): Promise<object>;
  /** 是否开启分页 */
  paged?: boolean;
  /** 默认排序字段 */
  sortField?: string;
  /** 默认排序方式（asc为正序，desc为倒序） */
  sortOrder?: PaginationTableOrderInfo['sortOrder'];
  /** 初始化组件的适合需要先执行的钩子函数 */
  beforeInit?(): Promise<any>;
  /** 加载完table之后需要先执行的钩子函数 */
  afterLoaded?(): Promise<any>;
}

const usePagination = (tableConfg: usePaginationConfig) => {
  const loading = ref(true);
  const lock = ref(false);
  const oldPage = ref(0);
  const currentPage = ref(1);
  const oldPageSize = ref(10);
  const pageSize = ref(10);
  const totalCount = ref(0);
  const dataList = ref<Awaited<ReturnType<typeof tableConfg.load>>['dataList']>(
    []
  );
  const paged = ref(tableConfg.paged);
  const orderInfo = reactive<PaginationTableOrderInfo>({
    sortField: tableConfg.sortField,
    sortOrder: tableConfg.sortOrder ?? null
  });
  const filterParams = ref({});
  /**
   * 获取表格数据核心方法
   * @param pageNo 当前分页
   * @param pageSize 每页数量
   * @param reload 是否重新加载
   */
  const loadPage = async (pageNo: number, pageSize: number, reload = false) => {
    try {
      /** 页码,页码Size 不变不执行 */
      if (
        oldPage.value === pageNo &&
        oldPageSize.value === pageSize &&
        !reload &&
        paged.value
      ) {
        return Promise.resolve();
      }
      /** 生成查询参数 */
      const params: loadDataParam = { queryParams: filterParams.value };
      params.orderParams =
        orderInfo.sortField != null && orderInfo.sortOrder != null
          ? orderInfo
          : undefined;
      if (paged.value) {
        params.pageParams = { pageNo, pageSize };
      }
      /** end */
      loading.value = true;
      const { dataList: list, totalCount: count } =
        await tableConfg.load(params);
      dataList.value = list;
      totalCount.value = count || list.length;
      return Promise.resolve();
    } catch (error) {
      return Promise.reject(error);
    } finally {
      loading.value = false;
    }
  };

  /**
   * 表格分页变化
   * @param {Integer} newCurrentPage 变化后的显示页面
   */
  const onCurrentPageChange = (newCurrentPage: number) => {
    if (lock.value) return Promise.resolve();
    return loadPage(newCurrentPage, pageSize.value)
      .then(() => (oldPage.value = currentPage.value = newCurrentPage))
      .catch(() => (currentPage.value = oldPage.value)); // 失败的话要重置回之前的页码
  };

  /**
   * 表格分页每页显示数量变化
   * @param newPageSize 变化后的每页显示数量
   */
  const onPageSizeChange = (newPageSize: number) => {
    pageSize.value = newPageSize;
    currentPage.value = 1;
    return loadPage(1, newPageSize)
      .then(() => {
        oldPage.value = currentPage.value;
        oldPageSize.value = pageSize.value;
      })
      .catch(() => {
        currentPage.value = oldPage.value;
        pageSize.value = oldPageSize.value;
      });
  };

  /**
   * 表格排序字段变化
   * @param {String} prop 排序字段的字段名
   * @param {String} order 正序还是倒序
   */
  const onSortChange = (
    prop: string,
    order: PaginationTableOrderInfo['sortOrder']
  ) => {
    if (!orderInfo.sortField && !prop) return;
    orderInfo.sortField = prop;
    orderInfo.sortOrder = order;
    return refresh(true);
  };

  /**
   *
   * @param research 是否需要重置页码刷新
   * @returns
   */
  const refresh = async (research = false) => {
    try {
      if (research && tableConfg.verifyParameter) {
        filterParams.value = await tableConfg.verifyParameter();
        dataList.value = [];
      }
      if (research) {
        lock.value = true;
        await loadPage(1, pageSize.value, true);
        // 这里进行了页码赋值 会触发起 onCurrentPageChange 函数
        oldPage.value = currentPage.value = 1;
      } else {
        // 当前页刷新
        await loadPage(currentPage.value, pageSize.value, true);
      }
      if (tableConfg.afterLoaded) return tableConfg.afterLoaded();
      return Promise.resolve();
    } catch (error) {
      return Promise.reject(error);
    } finally {
      lock.value = false;
    }
  };

  const reset = () => {
    oldPage.value = 0;
    currentPage.value = 1;
    totalCount.value = 0;
    orderInfo.sortField = undefined;
    orderInfo.sortOrder = null;
  };

  const setLoading = (isLoading: boolean) => {
    loading.value = isLoading;
  };

  onMounted(() => {
    if (tableConfg.beforeInit) tableConfg.beforeInit();
  });

  const tableInstance = ref({
    loading,
    oldPage,
    totalCount,
    currentPage,
    pageSize,
    dataList,
    reset,
    refresh,
    onCurrentPageChange,
    onPageSizeChange,
    onSortChange,
    setLoading
  });

  return tableInstance;
};

export default usePagination;
